home *** CD-ROM | disk | FTP | other *** search
- /*********************************************************************
-
- menus & windows.c
-
- This file contains the menu and window handling code for the
- QuickDraw GX unaware sample, "Simple Sample."
-
- Additional info can be found in the related develop #19 article,
- "Adding QuickDraw GX Printing to QuickDraw Applications."
-
- Dave Hersey, Apple Developer Technical Support.
-
- ——————— Edit Trail ———————
-
- constructed: 1/22/94 - dmh
- cleaned up for 2nd draft of develop article: 3/10/94 - dmh
- cleaned up for final: 4/14/94 - dmh
- removed sprintf calls, to avoid need for ANSI 8/16/94 - nick
- added NewGXPrintingEventProc to build
- descriptors for ppc 8/17/94 - nick
-
- *********************************************************************/
-
- #include "Simple Sample.h"
-
-
- /************************************************************
- MyCreateDocument - This routine is called to create a new
- document.
-
- *************************************************************/
-
- OSErr MyCreateDocument(char *docTitle, MyDocumentPtr *createdDocument)
- {
- OSErr err;
- WindowPtr documentWindow;
- long newPage;
-
- *createdDocument = nil;
-
- // Create a window for our document.
-
- documentWindow = (WindowPtr) NewCWindow(nil, &gWindowRect, (ConstStr255Param) docTitle, false, noGrowDocProc, (WindowPtr)-1L, true, 0L);
- require_action(documentWindow, CouldNotCreateWindow, err = MemError(););
-
- // Initialize our private data for the document.
-
- *createdDocument = (MyDocumentPtr) NewPtrClear(sizeof(MyDocumentRec));
- require_action(*createdDocument, CouldNotCreateDocRec, err = MemError(););
-
- // Create a print handle.
-
- (*createdDocument)->documentPrintHdl = (THPrint) NewHandle(sizeof(TPrint));
- err = MemError();
-
- if (!err)
- {
- PrOpen();
- PrintDefault((*createdDocument)->documentPrintHdl);
- PrClose();
- }
-
- /*
- If there were no errors, add 1 page to the document, and
- store a reference to our private data in the document's
- window's refCon field.
- */
- nrequire(err, CouldNotCreatePrintStuff);
-
- (*createdDocument)->numPages = 0;
- (*createdDocument)->documentWindow = documentWindow;
- (*createdDocument)->documentFSSpec.name[0] = 0; // Indicates that document has never
- // been saved.
- if (docTitle[0] > 31)
- docTitle[0] = 31;
-
- BlockMove(&docTitle[0], &(*createdDocument)->documentTitle[0], (long) docTitle[0] +1);
- newPage = 0;
- err = MyInsertPage(*createdDocument, &newPage);
- (*createdDocument)->curPage = newPage;
-
- // Set the refCon to point to our document info structure.
-
- nrequire(err, CouldNotInsertPage);
- SetWRefCon(documentWindow, (long) *createdDocument);
- require(err, NoProblems);
-
- CouldNotInsertPage:
- DisposHandle((Handle) (*createdDocument)->documentPrintHdl);
-
- CouldNotCreatePrintStuff:
- DisposePtr((Ptr) *createdDocument);
-
- CouldNotCreateDocRec:
- DisposeWindow(documentWindow);
-
- CouldNotCreateWindow:
- NoProblems:
- return err;
- }
-
-
- /************************************************************
- MyDisposeDocument - This routine is called when we need to
- dispose of a window.
-
- *************************************************************/
-
- void MyDisposeDocument(MyDocumentPtr whichDocument)
- {
- long numPages, pg;
- WindowPtr docWindow;
-
- // Dispose of our private data for each page of this document.
-
- numPages = whichDocument->numPages;
-
- for (pg = numPages; pg >= 1; pg--)
- MyDisposePage(whichDocument, pg);
-
- // Dispose of our document's print record and private data.
-
- if (whichDocument->documentPrintHdl != nil)
- DisposHandle((Handle) whichDocument->documentPrintHdl);
-
- DisposeWindow(whichDocument->documentWindow);
- DisposePtr((Ptr) whichDocument);
- }
-
-
- /************************************************************
- MyInsertPage - This routine is called when we need to add
- a page to a document. The page is added AFTER the page
- number passed (1-based). If whichPg is greater than the
- last page of the document, the new page is added to the
- end of the document. If whichPg is less than 1, the page
- is added to the beginning of the doc. The page number of
- the new page is returned in whichPg.
-
- *************************************************************/
-
- OSErr MyInsertPage(MyDocumentPtr whichDocument, long *whichPage)
- {
- OSErr err = noErr;
- long numPages, aPage;
- long newSize;
-
- // Pin the number of the page to add to the range (1, numPages +1).
-
- numPages = whichDocument->numPages;
- *whichPage = (*whichPage < 1)? 1: (*whichPage < numPages)? *whichPage +1: numPages +1;
-
- /*
- Do whatever you need to do to add page data here.
- .
- .
- .
-
- */
-
- numPages = ++whichDocument->numPages;
- return err;
- }
-
-
- /************************************************************
- MyDisposePage - This routine is called when we need to
- dispose of a page in a document.
-
- *************************************************************/
-
- void MyDisposePage(MyDocumentPtr whichDocument, long whichPage)
- {
- long numPages, pageNum;
- long newSize;
-
- // Idiot control.
-
- if (whichPage > whichDocument->numPages) return; // ?! There aren't that many pages!!
- if (whichPage < 1) return; // ?! Page numbers start at 1!!
-
- /*
- Do whatever you need to do to remove page data here.
- .
- .
- .
-
- */
-
- // We now have one less page in our document.
-
- numPages = --whichDocument->numPages;
- }
-
-
- /************************************************************
- MyUpdateWindow - This routine simply updates the passed
- window.
-
- *************************************************************/
-
- void MyUpdateWindow(WindowPtr whichWindow)
- {
- GrafPtr oldPort;
-
- // Update the indicated window.
-
- if (((WindowPeek) whichWindow)->windowKind == userKind)
- {
- GetPort(&oldPort);
- SetPort(whichWindow);
- BeginUpdate(whichWindow);
- MyDrawContents(whichWindow);
- EndUpdate(whichWindow);
- SetPort(oldPort);
- }
- }
-
-
- /************************************************************
- MyDrawContents - This routine draws the contents of a
- window. Note that this same code is used to draw during
- printing. All we do in this code is make a bunch of
- QuickDraw calls to draw our document's pages.
-
- *************************************************************/
-
- void MyDrawContents(WindowPtr whichWindow)
- {
- MyDocumentPtr windowDoc;
- PicHandle drawPict;
- Rect drawRect, drawRect2;
- short fNum, i, lineInc, hCenter, picWidth, picHeight;
- short oldResFile;
- FontInfo fInfo;
- Handle iconHdl;
- BitMap iconBitMap;
- Str255 pStr;
- Point where;
- GrafPtr curPort;
-
- // Preserve the current resource file in case we're printing.
-
- oldResFile = CurResFile();
- windowDoc = MyGetDocPtr(whichWindow);
-
- // Draw a red QuickDraw rectangle.
-
- ForeColor(redColor);
- SetRect(&drawRect, 20, 20, 150, 150);
- FrameRect(&drawRect);
-
- // Draw a blue QuickDraw oval.
-
- ForeColor(blueColor);
- OffsetRect(&drawRect, 40, 40);
- FrameOval(&drawRect);
-
- // Draw a black QuickDraw line with a 4x4 pen.
-
- ForeColor(blackColor);
- PenSize(4, 4);
- MoveTo(drawRect.left, drawRect.top);
- LineTo(drawRect.right, drawRect.bottom);
- PenSize(1, 1);
-
- // Draw some QuickDraw text with various faces.
-
- GetFNum("\pNew York", &fNum);
- TextFont(fNum);
- TextSize(10);
- GetFontInfo(&fInfo);
- lineInc = fInfo.ascent + fInfo.leading + fInfo.descent;
- TextFace(bold);
- MoveTo(220, 40);
- DrawString("\pFor Sale: ");
- TextFace(0);
- DrawString("\pEnglish sheepdog. ");
- TextFace(underline);
- DrawString("\pCompletely");
- TextFace(0);
- MoveTo(220, 40 + lineInc);
- DrawString("\phouse-broken, eats a lot, ");
- TextFace(italic);
- DrawString("\ploves cats and");
- MoveTo(220, 40 + 2* lineInc);
- DrawString("\psmall children.");
- TextFace(0);
- DrawString("\p Free to a good home.");
- MoveTo(220, 40 + 3* lineInc);
-
- // Draw two concentric QuickDraw rectangles around the text we just drew.
-
- GetPen(&where);
- drawRect.left = 216;
- drawRect.top = 30;
- drawRect.right = 450;
- drawRect.bottom = where.v - lineInc/2;
- FrameRect(&drawRect);
- InsetRect(&drawRect, -2, -2);
- FrameRect(&drawRect);
-
- /*
- Calculate the center of our window, and then draw a
- QuickDraw picture at that location.
- */
-
- hCenter = (whichWindow->portRect.right + whichWindow->portRect.left) >>1;
-
- UseResFile(gAppResRefNum);
- drawPict = GetPicture(r_documentPict);
- UseResFile(oldResFile);
-
- if (drawPict != nil)
- {
- picWidth = (*drawPict)->picFrame.right - (*drawPict)->picFrame.left;
- picHeight = (*drawPict)->picFrame.bottom - (*drawPict)->picFrame.top;
-
- drawRect.top = 240;
- drawRect.left = hCenter -(picWidth >>1);
- drawRect.bottom = drawRect.top + picHeight;
- drawRect.right = drawRect.left + picWidth;
-
- DrawPicture(drawPict, &drawRect);
- ReleaseResource((Handle) drawPict);
- }
-
- /*
- Load a QuickDraw icon, and CopyBits a bunch of them across
- the page, in various colors.
- */
-
- UseResFile(gAppResRefNum);
- iconHdl = (Handle) GetIcon(r_documentBitmap);
- UseResFile(oldResFile);
-
- if (iconHdl != nil)
- {
- MoveHHi((Handle) iconHdl);
- HLock((Handle) iconHdl);
- iconBitMap.rowBytes = 4;
- SetRect(&iconBitMap.bounds, 0, 0, 31, 31);
- iconBitMap.baseAddr = *iconHdl;
-
- drawRect.top = drawRect.bottom +20;
- drawRect.left = 10;
- drawRect.bottom = drawRect.top +31;
- drawRect.right = drawRect.left +31;
-
- for (i = 0; i < 12; i++)
- {
- switch (i % 6)
- {
- case 0:
- ForeColor(blackColor);
- break;
- case 1:
- ForeColor(blueColor);
- break;
- case 2:
- ForeColor(greenColor);
- break;
- case 3:
- ForeColor(redColor);
- break;
- case 4:
- ForeColor(cyanColor);
- break;
- case 5:
- ForeColor(magentaColor);
- break;
- }
-
- GetPort(&curPort);
- CopyBits(&iconBitMap, &curPort->portBits, &iconBitMap.bounds, &drawRect, srcCopy, nil);
-
- drawRect.left += 40;
- drawRect.right += 40;
- }
-
- ReleaseResource(iconHdl);
- }
-
- // Draw some more QuickDraw text. This time, blue and 24 point.
-
- GetFNum("\pTimes", &fNum);
- TextFont(fNum);
- TextSize(24);
- ForeColor(blueColor);
- // remove sprintf call, removes the need to link with the metrowerks ansi library
- // was: pStr[0] = sprintf((char *) &pStr[1], "These are some typical QuickDraw objects");
-
- {
- unsigned char *tempStr = "\pThese are some typical QuickDraw objects" ; // should come from a resource
- BlockMove( &tempStr[1], &pStr[1], tempStr[0] ) ;
- pStr[0] = tempStr[0] ;
-
-
- }
-
- MoveTo(hCenter -(StringWidth(pStr) >>1), drawRect.bottom +20);
- DrawString(pStr);
-
- // Draw some QuickDraw PicComments.
-
- MyDrawPicComments();
-
- /*
- Draw some more black QuickDraw text in a different font
- and size, indicating the page number.
- */
- GetFNum("\pGeneva", &fNum);
- TextFont(fNum);
- TextSize(12);
-
- ForeColor(blackColor);
- // remove sprintf call, removes the need to link with the metrowerks ansi library
- // was: pStr[0] = sprintf((char *) &pStr[1], "This is page %ld of %ld.",
- // windowDoc->curPage, windowDoc->numPages);
-
- {
- unsigned char *strPart1 = "\pThis is page " ; // should come from a resource
- unsigned char *strPart2 = "\p of " ; // should come from a resource
- unsigned char currentPage[32] ;
- unsigned char numberOfPages[32] ;
- short theLength = 0 ;
-
- NumToString( windowDoc->curPage, currentPage ) ;
- NumToString( windowDoc->numPages, numberOfPages ) ;
-
- BlockMove( &strPart1[1], &pStr[theLength + 1], strPart1[0] ) ;
- theLength += strPart1[0] ;
-
- BlockMove( ¤tPage[1], &pStr[theLength + 1], currentPage[0] ) ;
- theLength += currentPage[0] ;
-
- BlockMove( &strPart2[1], &pStr[theLength + 1], strPart2[0] ) ;
- theLength += strPart2[0] ;
-
- BlockMove( &numberOfPages[1], &pStr[theLength + 1], numberOfPages[0] ) ;
- theLength += numberOfPages[0] ;
-
- pStr[0] = theLength ;
-
- }
-
- MoveTo(hCenter -(StringWidth(pStr) >>1), drawRect.bottom +80);
- DrawString(pStr);
- }
-
-
- /************************************************************
- MyDrawPicComments - This routine just draws some example
- PicComments which will make a PostScript device display
- "This was drawn on a PostScript device." and other devices
- display "This was drawn on a non-PostScript device." We
- use PostScriptBegin PostScriptEnd and PostScriptHandle.
-
- *************************************************************/
-
- void MyDrawPicComments()
- {
- short fNum;
-
- /*
- Draw some QuickDraw to set the PS clip, not necessary in
- this case, but if we hadn't made any QuickDraw calls yet,
- the PostScript clip wouldn't get set, and *everything*
- would be clipped. This code, which doesn't actually draw
- anything, is here as a reminder.
- */
-
- PenSize(0, 0);
- MoveTo(0, 0);
- Line(0, 0);
- PenSize(1, 1);
-
- /*
- PostScriptBegin tells a PostScript driver to ignore Quickdraw
- calls until it receives a PostScriptEnd picture comment.
- This line is ignored by non-PostScript printer drivers.
- */
-
- PicComment(PostScriptBegin, 0, nil);
-
- /*
- QuickDraw representation. These calls will only be executed by
- QuickDraw printers. Set the font to Times Italic 14 pt and then
- move and draw.
- */
-
- GetFNum("\pTimes", &fNum);
- TextFont(fNum);
- TextSize(14);
- TextFace(italic);
- MoveTo(127, 227);
- DrawString("\pThis was drawn on a non-PostScript device.");
- TextFace(0);
-
- /*
- PostScript representation. These calls will only be executed by
- PostScript printers. We draw the same as above, sans the "non-"
- and shifted left a tad.
- */
-
- MySendPostScript("\p0 760 translate 1 -1 scale");
- MySendPostScript("\p/Times-Italic findfont 14 scalefont setfont");
- MySendPostScript("\p135 533 moveto (This was drawn on a PostScript device.) show");
-
- /*
- PostScriptEnd tells a PostScript driver to start executing
- QuickDraw calls normally again.
- */
-
- PicComment(PostScriptEnd, 0, nil);
- }
-
-
- /************************************************************
- MySendPostScript - This routine just packages the passed
- Pascal string into a handle and sends the PostScriptHandle
- PicComment.
-
- *************************************************************/
-
- void MySendPostScript(Str255 thePostScript)
- {
- OSErr err;
- Handle thePSHdl;
- Ptr thePSPtr;
- long textLen;
-
- /*
- Create a handle for the passed string plus a carriage
- return. Move the string's data into the handle, stuff a
- carriage return on the end, call PicComment, and finally
- dispose of the handle.
- */
- textLen = thePostScript[0];
- thePSHdl = TempNewHandle(textLen +1, &err);
-
- if (!err)
- {
- thePSPtr = *thePSHdl;
- BlockMove(&thePostScript[1], thePSPtr, textLen);
- *(thePSPtr +textLen) = (char) 13; //carriage return.
- ++textLen;
-
- PicComment(PostScriptHandle, textLen, thePSHdl);
- DisposHandle(thePSHdl);
- }
- }
-
-
- /************************************************************
- MyAdjustMenus - This routine enables and disables our
- menus and menu items.
-
- *************************************************************/
-
- void MyAdjustMenus()
- {
- WindowPtr activeWindow;
- MenuHandle appleMenu, fileMenu, editMenu, documentMenu;
- MyDocumentPtr activeDocument;
- Boolean docOpen, onFirstPage, onLastPage, maxPages, neverSaved;
-
- appleMenu = GetMHandle(mApple);
- editMenu = GetMHandle(mEdit);
- fileMenu = GetMHandle(mFile);
- documentMenu = GetMHandle(mDocument);
-
- EnableItem(appleMenu, iAbout);
- EnableItem(fileMenu, iQuit);
- EnableItem(fileMenu, iNew);
- EnableItem(fileMenu, iOpen);
-
- /*
- If we have a document open, we enable certain menu items.
- Otherwise, we don't.
- */
-
- activeWindow = FrontWindow();
-
- if (activeWindow)
- {
- if (((WindowPeek) activeWindow)->windowKind != userKind)
- activeWindow = nil;
- }
-
- docOpen = (activeWindow != nil);
-
- if (!docOpen) // No document open.
- {
- DisableItem(fileMenu, iPrint);
- DisableItem(fileMenu, iClose);
- DisableItem(fileMenu, iSave);
- DisableItem(fileMenu, iSaveAs);
- DisableItem(fileMenu, iPageSetup);
- DisableItem(documentMenu, iInsertPage);
- DisableItem(documentMenu, iDeletePage);
- DisableItem(documentMenu, iAheadPage);
- DisableItem(documentMenu, iBackPage);
- }
- else // A document is open.
- {
- EnableItem(fileMenu, iPrint);
- EnableItem(fileMenu, iClose);
- EnableItem(fileMenu, iPageSetup);
- EnableItem(fileMenu, iSaveAs);
-
- /*
- Enable/disable items based on the number of pages in our document,
- whether we're on the first or last page, and whether or not it's
- been saved yet.
- */
- activeDocument = MyGetDocPtr(activeWindow);
-
- if (activeDocument->numPages > 1) // Got at least one page?
- EnableItem(documentMenu, iDeletePage);
- else
- DisableItem(documentMenu, iDeletePage);
-
- onFirstPage = (activeDocument->curPage == 1);
- onLastPage = (activeDocument->curPage == activeDocument->numPages);
- maxPages = (activeDocument->numPages == kMaxPages);
- neverSaved = (activeDocument->documentFSSpec.name[0] == 0);
-
- if (neverSaved) // Never saved this document?
- DisableItem(fileMenu, iSave);
- else
- EnableItem(fileMenu, iSave);
-
- if (!maxPages) // Can still add more pages?
- EnableItem(documentMenu, iInsertPage);
- else
- DisableItem(documentMenu, iInsertPage);
-
- if (!onLastPage) // Not on last page?
- EnableItem(documentMenu, iAheadPage);
- else
- DisableItem(documentMenu, iAheadPage);
-
- if (!onFirstPage) // Not on first page?
- EnableItem(documentMenu, iBackPage);
- else
- DisableItem(documentMenu, iBackPage);
- }
- }
-
-
- /************************************************************
- MyDoMenuCommand - This routine handles the dispatching of
- our menu requests.
-
- *************************************************************/
-
- void MyDoMenuCommand(long menuResult)
- {
- short menuID, menuItem;
- long curPage, numPages, newPage;
- Str255 daName;
- OSErr err;
- WindowPtr activeWindow;
- MyDocumentPtr activeDocument, aDocument;
-
- menuID = menuResult >>16;
- menuItem = menuResult & 0x0000FFFF;
- activeWindow = FrontWindow();
- activeDocument = MyGetDocPtr(activeWindow);
-
- switch (menuID)
- {
- case mApple:
- switch (menuItem)
- {
- case iAbout: // About.
-
- Alert(r_About, nil);
- break;
-
- default: // DAs, etc.
-
- GetItem(GetMHandle(mApple), menuItem, daName);
- OpenDeskAcc(daName);
- break;
- }
- break;
-
- case mFile:
- switch (menuItem)
- {
- case iNew: // New or Open.
- case iOpen:
-
- err = MyCreateDocument(kDefaultTitle, &aDocument);
-
- if ((err == noErr) && (menuItem == iOpen))
- {
- err = MyLoadDocument(aDocument);
-
- if (err != noErr)
- MyDisposeDocument(aDocument);
- }
-
- if (err == noErr)
- {
- ShowWindow(aDocument->documentWindow);
- SelectWindow(aDocument->documentWindow);
- MyAdjustMenus();
- }
- break;
-
- case iClose: // Close.
-
- MyDisposeDocument(activeDocument);
- break;
-
- case iSave: // Save or Save As.
- case iSaveAs:
-
- err = MySaveDocument(activeDocument, (menuItem == iSaveAs));
- break;
-
- case iPageSetup: // Page Setup.
-
- if (MyDoPageSetup(activeDocument))
- MyRepaginateDoc(activeDocument);
- break;
-
- case iPrint: // Print.
-
- err = MyPrintDocument(activeDocument);
- break;
-
- case iQuit: // Quitting.
-
- gQuitting = true;
- break;
- }
- break;
-
- case mEdit: // If this were a real app, blah, blah, blah.
- break;
-
- case mDocument:
- switch (menuItem)
- {
- case iInsertPage: // Insert a page.
-
- newPage = activeDocument->curPage;
- MyInsertPage(activeDocument, &newPage);
- activeDocument->curPage = newPage;
- SetPort(activeWindow);
- EraseRect(&activeWindow->portRect);
- InvalRect(&activeWindow->portRect);
- break;
-
- case iDeletePage: // Delete current page.
-
- curPage = activeDocument->curPage;
- numPages = activeDocument->numPages;
-
- if (numPages > 1)
- {
- MyDisposePage(activeDocument, curPage);
-
- if (curPage == numPages)
- curPage = --activeDocument->curPage;
-
- SetPort(activeWindow);
- EraseRect(&activeWindow->portRect);
- InvalRect(&activeWindow->portRect);
- }
- break;
-
- case iAheadPage: // Display ahead one page.
-
- curPage = activeDocument->curPage;
- numPages = activeDocument->numPages;
-
- if (curPage < numPages)
- {
- ++activeDocument->curPage;
-
- SetPort(activeWindow);
- EraseRect(&activeWindow->portRect);
- InvalRect(&activeWindow->portRect);
- }
- break;
-
- case iBackPage: // Display back one page.
-
- curPage = activeDocument->curPage;
-
- if (curPage > 1)
- {
- --activeDocument->curPage;
-
- SetPort(activeWindow);
- EraseRect(&activeWindow->portRect);
- InvalRect(&activeWindow->portRect);
- }
- break;
- }
- break;
- }
-
- HiliteMenu(0);
- }
-
-
- /************************************************************
- MyGetDocPtr - This routine returns a pointer to the
- private document structure our application attaches to
- its windows.
-
- *************************************************************/
-
- MyDocumentPtr MyGetDocPtr(WindowPtr whichWindow)
- {
- MyDocumentPtr windowsDocument = nil;
-
- if (whichWindow != nil)
- windowsDocument = (MyDocumentPtr) GetWRefCon(whichWindow);
-
- return windowsDocument;
- }
-
-